package me.flyray.bsin.infrastructure.biz.paychannel.joinpay;

import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.constants.ResponseCode;
import me.flyray.bsin.exception.BusinessException;
import me.flyray.bsin.infrastructure.biz.paychannel.AbstractPaymentService;
import me.flyray.bsin.infrastructure.biz.paychannel.joinpay.domain.request.BaseRequest;
import me.flyray.bsin.infrastructure.biz.paychannel.joinpay.domain.request.UniPayReq;
import me.flyray.bsin.infrastructure.biz.paychannel.joinpay.util.SignatureUtil;
import me.flyray.bsin.payment.channel.wxpay.model.RefundUnifyReq;
import me.flyray.bsin.payment.channel.wxpay.model.UnifyOrderReq;
import me.flyray.bsin.payment.common.AbstractRes;
import me.flyray.bsin.payment.enums.PayChannelInterfaceEnum;
import me.flyray.bsin.payment.utils.PayWayUtil;
import me.flyray.bsin.utils.ValidatorUtils;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.function.Function;

@Slf4j
@Component
public class JoinPayPaymentService extends AbstractPaymentService {

    @Override
    public String getPayChannelCode() {
        return PayChannelInterfaceEnum.JOIN_PAY.getCode();
    }

    @Override
    public AbstractRes pay(UnifyOrderReq request) throws Exception {
        return Objects.requireNonNull(PayWayUtil.getRealPayWayService(this, request.getPayWay()))
                .pay( request );
    }

    @Override
    public AbstractRes refund(RefundUnifyReq request) throws Exception {
        return Objects.requireNonNull(PayWayUtil.getRealPayWayService(this, request.getPayWay()))
                .refund( request );
    }

    protected <T extends BaseRequest,V> V execute(T request, Function<T, V> clientCall){
        //处理公共参数
        handleCommonParam(request);
        //校验参数
        validateParams(request);
        //进行签名
        generateSignature(request);
        //调用支付接口
        return clientCall.apply(request);
    }

    /**
     * 处理公共参数
     * @param request
     */
    private void handleCommonParam(BaseRequest request){
        request.setVersion("2.5");
        request.setMerchantNo("test");
    }

    /**
     * 校验参数
     * @param request
     */
    private void validateParams(BaseRequest request){
        try{
            ValidatorUtils.validate(request);
        }catch (ValidationException e){
            throw new BusinessException(ResponseCode.PARAM_ERROR.getCode(), e.getMessage());
        }
    }

    /**
     * 签名
     * @param request
     */
    private void generateSignature(BaseRequest request){
        String hmac = SignatureUtil.buildHmac(request, "1111");
        request.setHmac(hmac);
    }

    protected UniPayReq buildUniPayReq(UnifyOrderReq unifyOrderReq){
        //回调地址
        String notifyUrl = getPayNotifyUrl(unifyOrderReq.getNotifyUrl(), unifyOrderReq.getOutOrderNo());
        return UniPayReq.builder()
                .amount(unifyOrderReq.getPayAmount())
                .orderNo(unifyOrderReq.getOutOrderNo())
                .cur("1")
                .productName(unifyOrderReq.getSubject())
                .productDesc(unifyOrderReq.getBody())
                .buyerId(unifyOrderReq.getCustomerNo())
                .notifyUrl(notifyUrl)
                .openId(unifyOrderReq.getChannelUserId())
                .frpCode("WEIXIN_XCX")
                .appId(unifyOrderReq.getBizRoleAppId())
                .tradeMerchantNo("")
                .build();
    }

}
